angular.module('web').factory('autoUpgradeSvs', [
  'settingsSvs',
  function(settingsSvs) {
    var util = require('./node/ossstore/lib/util');
    var NAME = 'oss-browser';

    var release_notes_url = Global.release_notes_url;
    var upgrade_url = Global.upgrade_url;
    var gVersion = Global.app.version;
    // var config_path = Global.config_path;

    var upgradeOpt = {
      currentVersion: gVersion,
      isLastVersion: false,
      lastVersion: gVersion,
      fileName: '',
      link: '',
      // fileName: fileName,
      // link: linkPre + '/'+ fileName,
      upgradeJob: {
        pkgLink: '',
        progress: 0,
        status: 'waiting'
      }
    };

    return {
      load: load,
      start: start,

      compareVersion: compareVersion,
      getReleaseNote: getReleaseNote,
      getLastestReleaseNote: getLastestReleaseNote
    };

    var job;

    function start() {
      if (job && job.status !== 'running') {
        job.start();
      }
    }

    function getReleaseNote(version, lang, fn) {
      if (compareVersion(version, '1.5.1') <= 0) { $.get('../release-notes/' + version + '.md', fn); } else { $.get('../release-notes/' + version + '.' + lang + '.md', fn); }
    }

    // 获取最新releaseNote
    function getLastestReleaseNote(version, lang, fn) {
      if (compareVersion(version, '1.5.1') <= 0) { $.get(release_notes_url + version + '.md', fn); } else { $.get(release_notes_url + version + '.' + lang + '.md', fn); }
    }

    function FlatDownloadJob(name, from, to) {
      console.log('FlatDownloadJob:', from, to);
      this.total = 0;
      this.progress = 0;
      this.name = name;
      this.from = from;
      this.to = to;

      var _statusChangeFn;
      var _progressChangeFn;

      this.update = function() {
        // copy
        console.log('copy:', __dirname);
        fs.renameSync(to + '.download', to);
        this._changeStatus('finished');
      };
      this.check = function(crc, md5, fn) {
        // crc
        console.log('crc64 check');

        return util.checkFileHash(to + '.download', crc, md5, fn);
      };

      this.precheck = function() {
        this.progress = 0;
        this.total = 0;

        if (fs.existsSync(to)) {
          console.log('exists, done');
          this.progress = 100;
          this._changeStatus('finished');
        }
      };

      this.start = function() {
        this.progress = 0;
        this.total = 0;
        var that = this;

        if (fs.existsSync(to)) {
          console.log('exists, done');
          this.progress = 100;
          this._changeStatus('finished');

          return;
        }

        if (fs.existsSync(to + '.download')) {
          fs.unlinkSync(to + '.download');
        }

        console.log('start download ...');
        that._changeStatus('running');

        request
            .head({ url: from, timeout: 10000 })
            .on('error', function(err) {
              console.log(err);
              this._changeStatus('failed', err);
            })
            .on('response', function(response) {
              console.log(response.statusCode); // 200
              console.log(response.headers); // 'image/png'

              if (response.statusCode == 200) {
                that.total = response.headers['content-length'];
                var current = 0;

                that.progress = Math.round((current * 10000) / that.total) / 100;
                console.log(that.total);

                var ws = fs.createWriteStream(to + '.download', { flags: 'a+' });

                request(from)
                    .on('error', function(err) {
                      console.log(err);
                      that._changeStatus('failed', err);
                    })
                    .on('data', function(chunk) {
                      current += chunk.length;
                      that.progress =
                    Math.round((current * 10000) / that.total) / 100;
                      // console.log(that.progress)
                      that._changeProgress(that.progress);

                      // fs.appendFile(to+'.download', chunk, function(err){
                      //    if(err)console.log(err)
                      // });
                      return chunk;
                    })
                    .pipe(ws)
                    .on('finish', function() {
                      that._changeStatus('verifying');

                      that.check(
                          response.headers['x-oss-hash-crc64ecma'],
                          response.headers['content-md5'],
                          function(err) {
                            console.log('check error:', err);

                            if (err) { that._changeStatus('failed', err); } else {
                              that.update();
                            }
                          }
                      );
                    });
              } else {
                console.log(response);
                that._changeStatus('failed', response);
              }
            });
      };
      this.onProgressChange = function(fn) {
        _progressChangeFn = fn;
      };
      this.onStatusChange = function(fn) {
        _statusChangeFn = fn;
      };
      this._changeStatus = function(status, err) {
        // console.log(status, err)
        this.status = status;
        this.message = err;

        if (_statusChangeFn) { _statusChangeFn(status); }
      };
      this._changeProgress = function(prog) {
        if (_progressChangeFn) { _progressChangeFn(prog); }
      };
    }

    function load(fn) {
      $.getJSON(upgrade_url, function(data) {
        var isLastVersion = compareVersion(gVersion, data.version) >= 0;
        var lastVersion = data.version;

        upgradeOpt.isLastVersion = isLastVersion;
        upgradeOpt.lastVersion = lastVersion;

        var fileName =
          NAME + '-' + process.platform + '-' + process.arch + '.zip';

        if (isLastVersion) {
          // 无需更新

          var link =
            data.package_url.replace(/(\/*$)/g, '') +
            '/' +
            data.version +
            '/' +
            fileName;

          console.log('download url:', link);

          fn({
            currentVersion: gVersion,
            isLastVersion: isLastVersion,
            lastVersion: lastVersion,
            fileName: fileName,
            link: link
          });

          return;
        }

        getFasterUrl(data.package_urls, lastVersion, function(linkPre) {
          if (data.files) {
            // 暂时只支持1个文件更新
            data.file = data.files.length > 0 ? data.files[0] : null;

            var jobs = [];

            // var fileName = NAME + '-' + process.platform + '-' + process.arch + '.zip';

            var pkgLink =
              linkPre +
              '/' +
              process.platform +
              '-' +
              process.arch +
              '/' +
              data.file;

            upgradeOpt.fileName = fileName;
            upgradeOpt.link = linkPre + '/' + fileName;
            upgradeOpt.upgradeJob.status = 'waiting';
            upgradeOpt.upgradeJob.progress = 0;
            upgradeOpt.upgradeJob.pkgLink = pkgLink;

            var jobsFinishedCount = 0;

            var to = path.join(__dirname, '..', lastVersion + '-' + data.file);

            job = new FlatDownloadJob(data.file, pkgLink, to);

            job.onStatusChange(function(status) {
              upgradeOpt.upgradeJob.status = status;
            });
            job.onProgressChange(function(progress) {
              upgradeOpt.upgradeJob.progress = progress;
            });
            job.precheck();

            // 增量更新
            fn(upgradeOpt);

            return;
          }

          // 全量更新
          // var fileName = NAME + '-' + process.platform + '-' + process.arch + '.zip';
          // var link = data['package_url'].replace(/(\/*$)/g, '') + '/' + lastVersion + '/' + fileName;

          var link = linkPre + '/' + fileName;

          console.log('download url:', link);

          fn({
            files: data.files,
            currentVersion: gVersion,
            isLastVersion: isLastVersion,
            lastVersion: lastVersion,
            fileName: fileName,
            link: link
          });
        }); // end getFasterUrl
      });
    }

    function getFasterUrl(arr, lastVersion, fn) {
      var fileName =
        NAME + '-' + process.platform + '-' + process.arch + '.zip';
      var c = 0;
      var t = [];

      _dig();
      function _dig() {
        var t1 = Date.now();
        var linkPre = arr[c].replace(/(\/*$)/g, '') + '/' + lastVersion;

        $.ajax({
          timeout: 5000,
          url: linkPre + '/' + fileName,
          headers: {
            Range: 'bytes=30-210'
          }
        }).then(
            function(data) {
              var t2 = Date.now();

              t.push({ time: t2 - t1, linkPre: linkPre });

              c++;

              if (c >= arr.length) { callback(); } else { _dig(); }
            },
            function(err) {
              var t2 = Date.now();

              t.push({ time: t2, linkPre: linkPre });
              console.log(arr[c], err);

              c++;

              if (c >= arr.length) { callback(); } else { _dig(); }
            }
        );
      }
      function callback() {
        t.sort(function(a, b) {
          return a.time > b.time ? 1 : -1;
        });
        console.log('getFasterUrl:', JSON.stringify(t, ' ', 2));
        fn(t[0].linkPre);
      }
    }

    function compareVersion(curV, lastV) {
      var arr = curV.split('.');
      var arr2 = lastV.split('.');

      var len = Math.max(arr.length, arr2.length);

      for (var i = 0; i < len; i++) {
        var a = parseInt(arr[i]);
        var b = parseInt(arr2[i]);

        if (a > b) {
          return 1;
        }

        if (a < b) {
          return -1;
        }
      }

      return 0;
    }
  }
]);
